﻿using System.CodeDom.Compiler;

namespace ShadowCode.Injection.Base;
/*
[AddService(ServiceLifetime)]
[AddService(ServiceLifetime, Keyed, TryAdd, Factory, Index, ServiceType)]
[AddService<Service>(ServiceLifetime)]

[AddOptions]
[AddOptions<Type>]
[AddOptions("sectionKey", Name = "nameValue"， Type = typeof(MyOptions<string>)))]
 */
public abstract class AttributeBase<TTarget> where TTarget : UnitBase
{
    protected readonly TransformData data;
    private TTarget? target;

    protected AttributeBase(TransformData data)
    {
        this.data = data;
        AttributeSyntax = data.SyntaxNode as AttributeSyntax
            ?? throw new Exception($"表达式不是目标类型：{data.SyntaxNode}");

        GenericArgument = GetGenericArgument();

        var arguments = AttributeSyntax.ArgumentList?.Arguments;
        if (arguments.HasValue && arguments.Value is { Count: > 0 })
            SetProperty(arguments.Value);
    }

    /// <summary>
    /// 特性节点
    /// </summary>
    public AttributeSyntax AttributeSyntax { get; }

    /// <summary>
    /// 特性泛型参数节点
    /// </summary>
    public TypeSyntax? GenericArgumentTypeSyntax { get; set; }

    /// <summary>
    /// 表示特性中使用的泛型参数
    /// </summary>
    public INamedTypeSymbol? GenericArgument { get; }

    /// <summary>
    /// 被标记特性的节点
    /// <br/> AddService (类型、构造函数)
    /// <br/> AddOptions (类型)
    /// </summary>
    public TTarget Target => target ??= GetTarget();

    public abstract string GroupKey { get; }

    private INamedTypeSymbol? GetGenericArgument()
    {
        if (AttributeSyntax.Name is not GenericNameSyntax genericTypeNode) return default;
        GenericArgumentTypeSyntax = genericTypeNode.TypeArgumentList.Arguments[0];
        return data.GetTypeSymbol(GenericArgumentTypeSyntax) as INamedTypeSymbol;
    }

    protected abstract TTarget GetTarget();

    protected abstract void SetProperty(SeparatedSyntaxList<AttributeArgumentSyntax> arguments);

    internal abstract void Buid(IndentedTextWriter writer);
}